<template>
  <div ref="root_node"
       class="end-game">
  </div>
</template>
<script>
import {
  ROOM_STATUS,
  PLAYER_STATUS,
  roomStatusToString,
  playerStatusToString,
} from '../../STATUS';
import render_player, { init_loader as render_player_init_loader } from './render_player';
import Vue from "vue";
import TWEEN, {
  L_ANI_TIME,
  B_ANI_TIME,
  M_ANI_TIME,
  S_ANI_TIME,
  Tween,
} from "../../core/Tween";
import { SCORE_TYPE } from '../../STATUS';
import Card, { CardList, CARD_LIST } from "../../core/Card";
import { stageComponentGenerator } from '../../core/componentGenerator';
Vue.component('scores', {
  template: `<span :style="{color:score>0?'green':score<0?'red':'#000'}">{{score>0?'+':score<0?'-':'+'}}{{Math.abs(score)}}</span>`,
  props: {
    score: Number
  }
});
export default stageComponentGenerator({
  name: 'end-game',
  data() {
    return {
      ROOM_STATUS,
      PLAYER_STATUS,
      msg: 'Welcome to Your Vue.js App'
    }
  },
  created() {
    const {
      unwatchers,
      app,
      loader
    } = this;
    render_player_init_loader(loader);
    PIXI.CardSpirte.init_loader(loader);
    loader.add("straight_flush_score", "game/paixing09.png");
    loader.add("four_score", "game/paixing08.png");
    loader.add("full_house_score", "game/paixing07.png");
    loader.add("flush_score", "game/paixing06.png");
    loader.add("straight_score", "game/paixing05.png");
    loader.add("three_score", "game/paixing04.png");
    loader.add("two_pair_score", "game/paixing03.png");
    loader.add("two_score", "game/paixing02.png");
    loader.add("any_score", "game/paixing01.png");

    loader.add("three_straight_score", "game/paixing11.png");
    loader.add("three_flush_score", "game/paixing12.png");
    loader.add("six_pair_score", "game/paixing10.png");
    loader.add("one_long_score", "game/paixing13.png");
    loader.add("king_long_score", "game/paixing14.png");
    loader.add("all_small_score", "game/paixing16.png");
    loader.add("all_big_score", "game/paixing15.png");

    loader.add("score_bg", "game/Game_UI_03.png");
    loader.add("score_bg_special", "game/Game_UI_06.png");
    loader.add("score_bg_head_win", "game/Victory.png");
    loader.add("score_bg_head_fail", "game/Failure.png");
    loader.add("confirm", "home/choujiang_confirm.png");

    loader.add("show_score_dialog", "game/xs.png");
    loader.add("hide_score_dialog", "game/yc.png");

    loader.add("gun", "game/gun.png");
    loader.add("boom1", "game/boom1.png");
    loader.add("boom2", "game/boom2.png");
    loader.add("boom3", "game/boom3.png");
    loader.add("boom4", "game/boom4.png");
    loader.add("hole1", "game/hole_file.png");
    loader.add("hole2", "game/hole.png");

    loader.onError.add(err => console.error(err))
    const ani_tween = new TWEEN();
    app._ticker.add(() => {
      // 动画控制器
      ani_tween.update();
    });
    this.draw_app = () => {
      console.log("DRAW WAITGAMER");
      const loader = this.loader;
      if (!loader) {// maybe run on after destroyed
        return
      }
      this.clearWatch();
      const resources = loader.resources;
      app.stage.destroy();
      const stage = app.stage = new PIXI.Container();
      const {
        width,
        height
      } = app.renderer;
      const bg = new PIXI.Sprite(resources.bg.texture);
      bg.width = width;
      bg.height = height;
      stage.addChild(bg);

      let is_inited = false;
      unwatchers[unwatchers.length] = this.$watch("room.data", async (data) => {
        if (!data) {
          return;
        }
        if (is_inited) {
          return
        }
        is_inited = true;
        const { results_list, players } = this.room.data;

        const { avatar_box_bounds, $cur_player, $other_players, } = await render_player.call(this, {
          app,
          stage,
          resources,
          width,
          height,
          un_watch: true,
          players: players,
          unwatchers,
        });

        const results = results_list.find(results => results.player_id === this.player.id);
        if (!results) {
          return;
        }
        // console.log(JSON.stringify(results, null, 2));

        function render_res_cards(submit_res_cards, submit_res_scores, $parent, pos_index = 0, gun = 1/*打枪信息*/) {
          // 显示卡牌
          const $res_container = new PIXI.Container();
          $parent.addChild($res_container);
          const cur_player_bounds = $cur_player.getBounds();
          // 牌型名字
          const $score_container = new PIXI.Container();
          $parent.addChild($score_container);

          if (width > height) {
            var res_width = width / 3;
            var res_height = height / 2;
            if (pos_index === 0) {
              $res_container.x = res_width;
              $res_container.y = res_height;
            } else if (pos_index === 1) {
              $res_container.x = res_width;
              $res_container.y = 0;
            } else if (pos_index === 2) {
              $res_container.x = 0;
              $res_container.y = res_height / 2;
            } else if (pos_index === 3) {
              $res_container.x = res_width * 2;
              $res_container.y = res_height / 2;
            }
          } else {
            var res_width = width / 2;
            var res_height = height / 3;
            if (pos_index === 0) {
              $res_container.x = res_width / 2;
              $res_container.y = res_height * 2;
            } else if (pos_index === 1) {
              $res_container.x = res_width / 2;
              $res_container.y = 0;
            } else if (pos_index === 2) {
              $res_container.x = 0;
              $res_container.y = res_height;
            } else if (pos_index === 3) {
              $res_container.x = res_width;
              $res_container.y = res_height;
            }
          }

          let ani_cards = ani_tween.Tween({}).to({}, 0).start();
          ["top", "mid", "btm"].forEach((type, j) => {
            if (!submit_res_cards[type]) {
              return
            }
            const $cards_container = new PIXI.Container();
            const card_list = submit_res_cards[type].map(Card.getIns)
            card_list.forEach((card, i) => {
              const $card = new PIXI.CardSpirte(card, resources);
              $card.x = $card.width * (i * .58 - 0.02);
              $cards_container.addChild($card);
            });
            if (j == 2) {
              $cards_container.maxWidthHeight(res_width / 5 * 4, res_height / 8 * 4);
            } else {
              $cards_container.maxWidthHeight(res_width / 5 * (j + 3), res_height / 8 * (j + 3));
            }
            $cards_container.x = res_width / 2 - $cards_container.width / 2;
            $cards_container.y = res_height / 4 * j;
            $res_container.addChild($cards_container);

            // 显示牌型名字
            const score_type = SCORE_TYPE.get(submit_res_scores[type].handle_weight);
            let $score_type;
            let score_type_ani;
            if (score_type) {
              $score_type = new PIXI.Sprite(resources[score_type + "_score"].texture);
              $score_type.maxWidth(res_width / 4);
              $score_type.x = $res_container.x; //- $score_type.width * 1.2
              $score_type.y = $res_container.y + $cards_container.y + $cards_container.height / 2 - $score_type.height / 2;
              $score_container.addChild($score_type);
              // 动画
              score_type_ani = ani_tween.Tween($score_type)
                .fadeIn(B_ANI_TIME);
            }
            // 动画
            const new_ani_cards = ani_tween.Tween($cards_container)
              .zoomIn(B_ANI_TIME)
              .delay(B_ANI_TIME);
            if ($score_type) {
              new_ani_cards.chain(score_type_ani);
            }

            ani_cards.chain(new_ani_cards);
            ani_cards = new_ani_cards;
          });

          // 特殊牌的直接显示：一排直接显示
          if (submit_res_cards.all) {
            const $cards_container = new PIXI.Container();
            const card_list = submit_res_cards.all.map(Card.getIns).sort((card_a, card_b) => card_a - card_b);
            const $card_list = card_list.map((card, i) => {
              const $card = new PIXI.CardSpirte(card, resources);
              // $card.x = $card.width * (i * .35 - 0.02);
              $cards_container.addChild($card);
              ani_tween.Tween($card)
                .to({
                  rotation: Math.PI / 11 * -(card_list.length / 2 - i - 0.5)
                }, 1000)
                .onStart(() => {
                  $card.pivot.set($card.width / 2, $card.height * 1.5);
                  $card.x += $card.width / 2;
                  $card.y += $card.height * 1.5;
                })
                .delay(1000)
                .start()
              // $card.rotation = ;
              return $card;
            });
            const unit_card_width = res_width * 1.4 / 5.53;
            $cards_container.maxWidth(unit_card_width);
            // $card_list.forEach($card=>{
            //   $card.x = 0;
            // });
            $cards_container.x = res_width / 2 - unit_card_width / 2;
            $cards_container.y = res_height / 4;
            $res_container.addChild($cards_container);

            // 显示牌型名字
            const score_type = SCORE_TYPE.get(submit_res_scores.top.handle_weight);
            let $score_type;
            let score_type_ani;
            if (score_type) {
              $score_type = new PIXI.Sprite(resources[score_type + "_score"].texture);
              $score_type.maxHeight(res_height / 4);
              $score_type.x = res_width / 2 - $score_type.width / 2;
              $score_type.y = res_height * 3 / 4 - $score_type.height / 2;
              $res_container.addChild($score_type);
              // 动画
              score_type_ani = ani_tween.Tween($score_type)
                .fadeIn(B_ANI_TIME);
            }

            // 动画
            const new_ani_cards = ani_tween.Tween($cards_container)
              .zoomIn(B_ANI_TIME)
              .delay(B_ANI_TIME);
            if ($score_type) {
              new_ani_cards.chain(score_type_ani);
            }

            ani_cards.chain(new_ani_cards);
            ani_cards = new_ani_cards;
          }
          $res_container.x += res_width * 0.1;
          $res_container.y += res_height * 0.1;
          $res_container.scale.set(0.8);

          // 显示打枪
          $parent.getResContainer = () => {
            return $res_container
          }
          ani_cards.onComplete(() => {
            setTimeout(function () {
              $parent.emit("animation-complete", $res_container)
            }, B_ANI_TIME / 20)
          });
          // if(gun >= 2){
          // }else if(gun <= -2){

          // }
        }

        const PLAYER_RES_PLANEL_MAP = new Map();

        // 显示用户的牌组面板
        const $res_cards_parent_cur = new PIXI.Container();
        stage.addChild($res_cards_parent_cur);
        PLAYER_RES_PLANEL_MAP.set(this.player.id, $res_cards_parent_cur);
        ani_tween.Tween($cur_player)
          .to({
            x: $cur_player.x + (-width / (width > height ? 6 : 4) - avatar_box_bounds.width / 2),
          }, B_ANI_TIME)
          .start()
          // .onComplete(()=>{
          .onComplete(() => {
            render_res_cards(results.submit_res_cards, results.submit_res_scores, $res_cards_parent_cur, 0);
          })
        const [$other_player_1, $other_player_2, $other_player_3] = $other_players.children;
        [$other_player_1, $other_player_2, $other_player_3].forEach(($other_player, i) => {
          if ($other_player) {
            $other_player.setStatusHandler(($status) => {
              const player = this.room.players.find(player => player.id === $other_player.player_id)
              // console.log("recheck status",player)
              if (player) {
                if (player.status === PLAYER_STATUS.READY) {
                  $status.visible = true
                } else {
                  $status.visible = false
                }
              } else {
                // 离开房间，考虑到可能还会重新进入房间，$status对象必须改为单一对象才能使用$watch
              }
            });
            const $res_cards_parent = new PIXI.Container();
            stage.addChild($res_cards_parent);
            const one_vs_one = results.one_vs_one_list.find(one_vs_one => one_vs_one.player_id === $other_player.player_id);
            PLAYER_RES_PLANEL_MAP.set(one_vs_one.player_id, $res_cards_parent);

            const ani_to = {};
            if (i === 0) {
              ani_to.x = $other_player.x + width / (width > height ? 6 : 4);//+ avatar_box_bounds.width / 2;
            }
            ani_tween.Tween($other_player)
              .to(ani_to, B_ANI_TIME)
              .start()
              .onComplete(() => {
                // 显示卡牌
                render_res_cards(one_vs_one.submit_res_cards, one_vs_one.submit_res_scores, $res_cards_parent, i + 1, one_vs_one.multiple);
              });
          }
        });

        // 枪与子弹的容器
        const $gun_bullet_container = new PIXI.Container();
        stage.addChild($gun_bullet_container);

        // 显示隐藏分数面板按钮
        const $toggle_btm = new PIXI.Sprite(resources.show_score_dialog.texture);
        let $score_dialog;
        // 分数面板
        let _inited_show_score_dialog = false;
        // 用户头像组
        const player_ins = [];
        const show_score_dialog = () => {
          if (_inited_show_score_dialog) {
            return false
          }
          _inited_show_score_dialog = true;
          $score_dialog = (() => {
            const $dialog = new PIXI.Container();
            const $bg_mask = new PIXI.Graphics();
            $bg_mask.beginFill(0x0, 0.8);
            $bg_mask.drawRect(0, 0, width, height);
            $bg_mask.endFill();
            $dialog.addChild($bg_mask);

            // 计分面板
            const $bg = new PIXI.Sprite(resources.score_bg_special.texture);
            $bg.maxWidthHeight(width * 0.8, height * 0.8);
            $bg.x = width / 2 - $bg.width / 2;
            $bg.y = height / 2 - $bg.height / 2;
            $bg.tint = results.total >= 0 ? 0xFFff22 : 0xFFFFFF;
            $dialog.addChild($bg);

            // 头部
            const $bg_title = new PIXI.Sprite(resources[results.total >= 0 ? "score_bg_head_win" : "score_bg_head_fail"].texture)
            $bg_title.maxWidth($bg.width * 0.8);
            $bg_title.x = $bg.x + $bg.width / 2 - $bg_title.width / 2;
            $bg_title.y = $bg.y - $bg_title.height * 0.35;
            $dialog.addChild($bg_title);

            // 分数
            const fontSize = $bg.width / 30;
            const minFontSize = fontSize / 2;

            // $dialog.addChild($cur_player);
            // $dialog.addChild($other_players);
            // 用户组
            const $players = new PIXI.Container();
            $players.addChild($cur_player);
            $players.addChild(...$other_players.children);
            $dialog.addChild($players);
            const unit_width = $bg.width / ($players.children.length + 1);
            $players.children.forEach(($player, i) => {
              player_ins.push($player);
              $player._backup_1 = {
                width: $player.width,
                height: $player.height,
                x: $player.x,
                y: $player.y,
                parent: $other_players,
              }
              const _backup_2 = $player._backup_2 = {
                parent: $players
              };

              const res_height = Math.min($bg.height * 0.4, $player.height);
              const {
              height: old_height,
            } = $player;
              $player.maxHeight(res_height);
              _backup_2.width = $player.width;
              _backup_2.height = $player.height;
              const {
              width: new_width,
                height: new_height,
            } = $player;
              $player.maxHeight(old_height);
              const new_avatar_box_width = new_height / old_height * avatar_box_bounds.width;

              ani_tween.Tween(Object.assign({
                height: $player.width
              }, $player.getPos()))
                .to({
                  x: _backup_2.x = (i + 1) * unit_width - new_avatar_box_width / 2,
                  y: _backup_2.y = 0,
                  height: new_height,
                }, B_ANI_TIME)
                .onUpdate(function () {
                  $player.moveTo(this.x, this.y);
                  $player.maxHeight(this.height);
                })
                .onComplete(() => {
                  const player_results = results_list.find(player_results => player_results.player_id === $player.player_id);
                  if (player_results) {
                    const info = player_results.total;
                    let color = 0xFFFFFF;
                    if (typeof info === "number") {
                      if (info > 0) {
                        info = "+" + info;
                        color = 0x00FF33;
                      } else {
                        info = " " + info;
                        color = 0xFF0033;
                      }
                    }
                    $player.showText(new PIXI.Text(info, {
                      fill: color,
                      fontSize: fontSize
                    }));
                  }
                })
                .start();
            });
            ani_tween.Tween($players)
              .to({
                x: $bg.x,
                y: $bg.y + $bg.height * 0.2
              }, B_ANI_TIME)
              .start();

            // 描述与按钮
            const $info = new PIXI.Text("点击确定，即可开始下一局游戏", {
              fill: 0xFFFFFF,
              fontSize
            });
            $info.x = $bg.x + $bg.width / 2 - $info.width / 2;
            $info.y = $bg.y + $bg.height * 0.7 - $info.height / 2;
            $dialog.addChild($info);
            const $btm = new PIXI.Sprite(resources.confirm.texture);

            $btm.maxWidth(fontSize * 7);
            $btm.x = $bg.x + $bg.width / 2 - $btm.width / 2;
            $btm.y = $bg.y + $bg.height * 0.85 - $btm.height / 2;
            $dialog.addChild($btm);
            $btm.hover(() => $btm.tint = 0x999999, () => $btm.tint = 0xFFFFFF);
            $btm.bindTap(() => {
              this.restartGame()
            });

            return $dialog;
          })();
          stage.addChildBefore($score_dialog, $toggle_btm);
          // ani_tween.Tween($score_dialog)
          //   .fadeIn(B_ANI_TIME)
          //   .start()
          //   .onComplete(()=>{
          //   });
          // $score_dialog.visible = false;
          return $score_dialog;
        };

        // 按钮的操作
        let show = false;
        let cur_ani;
        const click_show_score_dialog = () => {
          show_score_dialog();
          if (cur_ani) {
            ani_tween.remove(cur_ani);
          }
          const { width, height } = $toggle_btm;
          if (show) {
            $toggle_btm.texture = resources.show_score_dialog.texture;
            cur_ani = ani_tween.Tween($score_dialog).fadeOut(B_ANI_TIME, $score_dialog.alpha).start().onComplete(() => {
              player_ins.forEach($player => {
                const _backup_1 = $player._backup_1;
                for (let k in _backup_1) {
                  if (k === "parent") {
                    _backup_1[k].addChild($player);
                  } else {
                    $player[k] = _backup_1[k];
                  }
                }
              });
              $score_dialog.visible = false
            });
          } else {
            $toggle_btm.texture = resources.hide_score_dialog.texture;
            cur_ani = ani_tween.Tween($score_dialog).fadeIn(B_ANI_TIME, $score_dialog.alpha).start().onStart(() => {
              player_ins.forEach($player => {
                const _backup_2 = $player._backup_2;
                for (let k in _backup_2) {
                  if (k === "parent") {
                    _backup_2[k].addChild($player);
                  } else {
                    $player[k] = _backup_2[k];
                  }
                }
              });
              $score_dialog.visible = true
            });
          }
          $toggle_btm.width = width;
          $toggle_btm.height = height;
          show = !show;
        }
        $toggle_btm.bindTap(click_show_score_dialog);
        $toggle_btm.maxWidthHeight(width * 0.1, height * 0.3);
        $toggle_btm.x = width * 0.9 - $toggle_btm.width / 2;
        $toggle_btm.y = height - $toggle_btm.height;
        stage.addChild($toggle_btm);
        // setTimeout(()=>{

        // }, 3000);

        /* 打枪动画*/
        const boom_frames = [];
        const hole_frames = [];

        const fly_bullet = (from_x, from_y, to_x, to_y, cb) => {
          if (!boom_frames.length) {
            for (let i = 1; i <= 4; i++) {
              // magically works since the spritesheet was loaded with the pixi loader
              boom_frames.push(resources["boom" + i].texture);
            }
            for (let i = 1; i <= 2; i++) {
              // magically works since the spritesheet was loaded with the pixi loader
              hole_frames.push(resources["hole" + i].texture);
            }
          }
          const boom_ani = new PIXI.extras.AnimatedSprite(boom_frames);
          boom_ani.maxWidthHeight(width / 8, height / 8);
          boom_ani.anchor.set(0.5);
          boom_ani.animationSpeed = 0.1;
          boom_ani.loop = false;
          $gun_bullet_container.addChild(boom_ani);
          boom_ani.play();
          // 子弹移动的轨道
          ani_tween.Tween(boom_ani)
            .set({
              x: from_x,
              y: from_y,
              alpha: 0,
            })
            .to({
              x: to_x,
              y: to_y,
              alpha: 1,
            }, B_ANI_TIME)
            .easing(TWEEN.Easing.Cubic.Out)
            .start();
          boom_ani.onComplete = function () {
            boom_ani.destroy();
            // 留下弹孔
            const hole_ani = new PIXI.extras.AnimatedSprite(hole_frames);
            hole_ani.maxWidthHeight(width / 8, height / 8);
            hole_ani.maxWidth(hole_ani.width * (1 + (Math.random() - 0.5) / 2));
            // hole_ani.rotation = Math.random()*Math.PI; // 旋转会使贴图的光影效果不对
            hole_ani.x = to_x;
            hole_ani.y = to_y;
            hole_ani.alpha = 0.9;
            hole_ani.anchor.set(0.5);
            hole_ani.animationSpeed = 0.1;
            hole_ani.loop = false;
            $gun_bullet_container.addChild(hole_ani);
            hole_ani.play();
            hole_ani.onComplete = cb;
          }
        };
        function get_two_point_deg(center_x, center_y, x, y) {
          let turn_deg = Math.atan((center_x - x) / (center_y - y)) * 180 / Math.PI;
          // turn_deg = -turn_deg;
          // turn_deg -= 90;
          if (y > center_y) {
            if (x < center_x) {
              turn_deg -= 180;
            } else {
              turn_deg += 180;
            }
          }
          return turn_deg;
        }
        function boom_from_gun(gun_x, gun_y, boom_x, boom_y, ani) {
          const $gun = new PIXI.Sprite(resources.gun.texture);
          $gun.maxWidthHeight(width / 4, height / 4);
          $gun.anchor.set(0.4, 0.2);
          $gun.x = gun_x;
          $gun.y = gun_y;
          $gun.rotation = Math.PI / 180 * -90;
          // let turn_deg = Math.atan((gun_y - boom_y) / (gun_x - boom_x)) * 180 / Math.PI;
          // if(turn_deg<0){
          //   turn_deg+=180;
          // }
          // turn_deg -= 90;
          // turn_deg = -turn_deg;
          // if(boom_y > gun_y){
          //   turn_deg+=180
          // }
          let turn_deg = get_two_point_deg(gun_x, gun_y, boom_x, boom_y);
          console.log("turn_deg", turn_deg)
          $gun.rotation += Math.PI / 180 * -turn_deg;
          $gun.fireBullet = function (to_x, to_y) {
            const res_rotation = this.rotation;
            const {
            x: from_x,
              y: from_y
          } = this;

            let _call_end_times = 0;
            this.on("fire-end", () => {
              _call_end_times += 1;
              if (_call_end_times === 2) {
                ani_tween.Tween(this)
                  .fadeOut()
                  .start()
                  .onComplete(() => this.destroy())
              }
            })
            const gun_end_ani = ani_tween.Tween(this)
              .to({
                rotation: res_rotation
              }, 600)
              .onComplete(() => this.emit("fire-end"))
            const gun_start_ani = ani_tween.Tween(this)
              .to({
                rotation: res_rotation - Math.PI / 180 * 20
              }, 120)
              .chain(gun_end_ani)
              .onStart(() => {
                $gun_bullet_container.addChild(this);
                fly_bullet(from_x, from_y, to_x, to_y, () => this.emit("fire-end"));
              });
            ani.chain(gun_start_ani);
            return gun_end_ani;
          }
          return $gun.fireBullet(boom_x, boom_y)
        }
        let gun_fire_ani = ani_tween.Tween({ a: 0 })
          .to({ a: 1 }, B_ANI_TIME)

        const first_gun_fire_ani = gun_fire_ani;
        results_list.forEach(results => {
          // console.log(JSON.stringify(results,null,2))
          const $res_cards_parent_1 = PLAYER_RES_PLANEL_MAP.get(results.player_id);
          $res_cards_parent_1.once("animation-complete", () => {
            const $res_container_1 = $res_cards_parent_1.getResContainer();
            const self_x = $res_container_1.x + $res_container_1.width / 2;
            const self_y = $res_container_1.y + $res_container_1.height / 2;
            const gun_fire_infos = results.one_vs_one_list.map(one_vs_one => {
              if (Math.abs(one_vs_one.multiple) >= 2) {
                const $res_cards_parent_2 = PLAYER_RES_PLANEL_MAP.get(one_vs_one.player_id);
                const $res_container_2 = $res_cards_parent_2.getResContainer();
                const res_width = $res_container_2.width;
                const res_height = $res_container_2.height;
                const target_x = $res_container_2.x + res_width / 2;
                const target_y = $res_container_2.y + res_height / 2;
                if (one_vs_one.top > 0) { // 目标中弹
                  gun_fire_ani = boom_from_gun(self_x, self_y,
                    target_x + (Math.random() - 0.5) * res_width / 2,
                    target_y + (Math.random() - 0.5) * res_height / 2,
                    gun_fire_ani);
                  return {
                    self_x,
                    self_y,
                    target_x,
                    target_y,
                    res_width,
                    res_height
                  }
                }
              }
            }).filter(info => info);
            if (gun_fire_infos.length === 3) { // 通杀额外的动画
              const new_gun_fire_ani = ani_tween.Tween({}).to({}, 1)
              let ani_times = 0;
              const complete_cb = () => {
                ani_times += 1;
                if (ani_times === 6) {
                  new_gun_fire_ani.start();
                }
              }
              gun_fire_ani.onComplete(() => {
                for (let {
                  target_x,
                  target_y,
                  res_width,
                  res_height
                }
                  of gun_fire_infos) {
                  setTimeout(() => {
                    fly_bullet(
                      target_x,
                      target_y,
                      target_x + (Math.random() - 0.5) * res_width / 2,
                      target_y + (Math.random() - 0.5) * res_height / 2,
                      complete_cb
                    );
                  }, 500 * Math.random())
                  setTimeout(() => {
                    fly_bullet(
                      target_x,
                      target_y,
                      target_x + (Math.random() - 0.5) * res_width / 2,
                      target_y + (Math.random() - 0.5) * res_height / 2,
                      complete_cb
                    );
                  }, 1000 * Math.random())
                }
              });
              gun_fire_ani = new_gun_fire_ani;
            }
            if (!first_gun_fire_ani.is____started) {
              first_gun_fire_ani.is____started = true
              first_gun_fire_ani.start();
            }
          });
        });

        gun_fire_ani.onComplete(() => {
          setTimeout(() => {
            if (!_inited_show_score_dialog) {
              click_show_score_dialog();
            }
          }, 3000)
        });
      }, { immediate: true });
    }
  },
  methods: {
    // cartNameToHtml(card) {
    //   const card_info = card.split("_");
    //   const [type, num] = card_info;
    //   const symbol_map = {
    //     "黑桃": "♠",
    //     "方块": "♦",
    //     "红心": "♥",
    //     "梅花": "♣",
    //   };
    //   const color_map = {
    //     "黑桃": "#000",
    //     "方块": "#e30",
    //     "红心": "#F00",
    //     "梅花": "#333",
    //   };
    //   return `<div class='img' style="color:${color_map[type]};">
    //     <div class='symbol'>${symbol_map[type]}</div>
    //     <div class='number'>${num}</div>
    //   </div>`
    // },
    roomStatusToString,
    playerStatusToString,
    restartGame() {
      socket.emit("restart")
    },
    getTotalByPlayerId(player_id) {
      for (var results of this.room.data) {
        if (results.player_id === player_id) {
          return results.total;
        }
      }
    }
  }
})
</script>
<style>
.end-game {
  width: 100%;
  height: 100%;
}
</style>